home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / viewers / msgifscn / gifscn.c < prev    next >
C/C++ Source or Header  |  1991-06-17  |  17KB  |  629 lines

  1. /* GIFSCAN - scans through a GIF file and reports all parameters */
  2.  
  3. #ifndef lint
  4. static char *SCCSid = "@(#)gifscn.c v1.2 changed 5/16/91 13:35:03";
  5. #endif
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9.  
  10. /* global values */
  11. int Quiet = 0;                  /* don't print detail */
  12. int Debug = 0;                  /* print debug/trace info */
  13. extern int optind, opterr;
  14. extern char *optarg;
  15.  
  16. /************************************************************************/
  17.  
  18. /* COLORMAP - reads color information in from the GIF file and displays */
  19. /*            it in a user selected method.  This display may be in :   */
  20. /*            hexidecimal (default), percentage, or decimal.  User      */
  21. /*            selects output method by placing a switch (-d, -p, -h)    */
  22. /*            between the program name and GIF filename at request time.*/
  23.  
  24. colormap(out, dev, times, file_byte_cnt)
  25. FILE *dev;                  
  26. int times;
  27. int out;
  28. int *file_byte_cnt;
  29.  
  30. #define DECIMAL 1
  31. #define PERCENT 2
  32. #define HEXIDEC 3
  33. #define MAX 255
  34.  
  35. {
  36.     unsigned int red;
  37.     unsigned int green;
  38.     unsigned int blue;
  39.  
  40.     int print_cnt;
  41.     int i;
  42.  
  43.             /* Start of procedure */
  44.  
  45.     if (!Quiet) {
  46.         if (out == DECIMAL)
  47.             printf ("\nColor definitions in decimal   (index #, R, G, B)\n");
  48.  
  49.         if (out == PERCENT)
  50.             printf ("\nColor definitions by percentage   (index #, R, G, B)\n");
  51.  
  52.         if (out == HEXIDEC)
  53.             printf ("\nColor definitions in hexidecimal    (index #, R, G, B)\n");
  54.     }
  55.  
  56.             /* read and print the color definitions */
  57.  
  58.     print_cnt = 0;
  59.  
  60.     for (i = 0; (i < times); i++)
  61.     {
  62.         red = getc(dev);
  63.         green = getc(dev);
  64.         blue = getc(dev);
  65.  
  66.         *file_byte_cnt += 3;
  67.  
  68.         if (!Quiet) switch (out)
  69.         {
  70.             case DECIMAL :
  71.                 printf ("%3d - %3d %3d %3d  ", i, red, green, blue);
  72.                 break;
  73.  
  74.             case PERCENT :
  75.                 red = (red * 100) / MAX;
  76.                 green = (green * 100) / MAX;
  77.                 blue = (blue * 100) / MAX;
  78.                 printf ("%3d - %3d %3d %3d  ", i, red, green, blue);
  79.                 break;
  80.  
  81.             case HEXIDEC :
  82.                 printf ("%3d - %2x %2x %2x   ", i, red, green, blue);
  83.                 break;
  84.         }
  85.   
  86.         print_cnt++;
  87.  
  88.         if (!Quiet && print_cnt == 4)
  89.         {
  90.             printf ("\n");
  91.             print_cnt = 0;
  92.         }
  93.     }
  94.     if (!Quiet && (times % 4) != 0)
  95.         printf ("\n");
  96. }
  97.  
  98. /************************************************************************/
  99.  
  100. /* GETBYTES - routine to retrieve two bytes of information from the GIF */
  101. /*            file and then shift them into correct byte order.  The    */
  102. /*            information is stored in Least Significant Byte order.    */
  103.  
  104. unsigned int getbytes(dev, file_byte_cnt)
  105.  
  106. FILE *dev;
  107. int *file_byte_cnt;
  108.  
  109. {
  110.     int byte1;
  111.     int byte2;
  112.     int result;
  113.  
  114.             /* read bytes and shift over */
  115.  
  116.     byte1 = getc(dev);
  117.     byte2 = getc(dev);
  118.  
  119.     *file_byte_cnt += 2;
  120.  
  121.     result = (byte2 << 8) | byte1;
  122.  
  123.     return result;
  124.  
  125. }
  126.  
  127. /***********************************************************************/
  128.  
  129. /* IMAGEINF - routine to read the GIF image information and display it */
  130. /*            to the user's screen in an orderly fasion.  If there are */
  131. /*            multiple images then IMAGEINF will be called to display  */
  132. /*            multiple screens.                                        */
  133.  
  134. imageinf(dev, bits_to_use, color_style, file_byte_cnt)
  135. FILE *dev;
  136. int bits_to_use;
  137. int color_style;
  138. int *file_byte_cnt;
  139.  
  140. {
  141.     int byte1;
  142.     int byte2;
  143.     int byte3;
  144.     int image_left;
  145.     int image_top;
  146.     int data_byte_cnt;
  147.     int bits_per_pix;
  148.     int color_res;
  149.     int colors;
  150.     int i;
  151.     int local;
  152.     int unexpected;
  153.  
  154.     unsigned int width;
  155.     unsigned int height;
  156.  
  157.     unsigned long bytetot;
  158.     unsigned long possbytes;
  159.  
  160.             /* determine the image left value */
  161.  
  162.     image_left = getbytes(dev, file_byte_cnt);
  163.  
  164.             /* determine the image top value */
  165.  
  166.     image_top = getbytes(dev, file_byte_cnt);
  167.     printf ("\nImage Left:     %5d\t\tImage Top:     %5d", image_left,
  168.                                                            image_top);
  169.  
  170.             /* determine the image width */
  171.  
  172.     width = getbytes(dev, file_byte_cnt);
  173.  
  174.             /* determine the image height */
  175.  
  176.     height = getbytes(dev, file_byte_cnt);
  177.     printf ("\nImage Width:    %5d\t\tImage Height:  %5d", width, height);
  178.  
  179.             /* check for interlaced image */
  180.  
  181.     byte1 = getc(dev);
  182.     (*file_byte_cnt)++;
  183.  
  184.     byte2 = byte1 & 0x40;
  185.     if (byte2 == 0x40)
  186.         printf ("\nInterlaced: Yes");
  187.     else
  188.         printf ("\nInterlaced: No");
  189.  
  190.             /* check for a local map */
  191.  
  192.     byte2 = byte1 & 0x80;
  193.     if (byte2 == 0x80)
  194.     {
  195.         local = 1;
  196.         printf ("\nLocal Color Map: Yes");
  197.     }
  198.     else
  199.     {
  200.         local = 0;
  201.         printf ("\nLocal Color Map: No");
  202.     }
  203.  
  204.             /* check for the 3 zero bits */
  205.  
  206.     byte2 = byte1 & 0x38;
  207.     if (byte2 != 0)
  208.         printf ("\n? -- Reserved zero bits in image not zeros.\n");
  209.  
  210.             /* determine the # of color bits in local map */
  211.  
  212.     bits_per_pix = byte1 & 0x07;
  213.     bits_per_pix++;
  214.     colors = 1 << bits_per_pix;
  215.  
  216.     if (local == 1)
  217.     {
  218.         bits_to_use = bits_per_pix;
  219.         printf ("\nBits per pixel: %5d\t\t# colors :     %5d", bits_per_pix,
  220.                                                                colors);
  221.         colormap (color_style, dev, colors, file_byte_cnt);
  222.     }
  223.  
  224.             /* retrieve the code size */
  225.  
  226.     byte1 = getc(dev);
  227.     (*file_byte_cnt)++;
  228.  
  229.     if ((byte1 < 2) || (byte1 > 8))
  230.     {
  231.         printf ("\n? -- Code size %d at start of image");
  232.         printf ("\n     is out of range (2-8).\n");
  233.     }
  234.     else
  235.         printf ("\nLZW min code size (bits):  %3d", byte1);
  236.  
  237.             /* tally up the total bytes and read past each data block */
  238.  
  239.     bytetot = 0;
  240.     possbytes = 0;
  241.  
  242.     while ((data_byte_cnt = getc(dev)) > 0)
  243.     {
  244.         (*file_byte_cnt)++;
  245.         bytetot = bytetot + data_byte_cnt;
  246.         if (!Quiet) printf("\n Record size %d",data_byte_cnt);
  247.         for (i = 0; (i < data_byte_cnt); i++)
  248.         {
  249.             byte2 = getc(dev);
  250.             (*file_byte_cnt)++;
  251.             if (byte2 == EOF)
  252.             {
  253.                 (*file_byte_cnt)--;
  254.                 printf ("\n? -- EOF reached inside image data block.\n");
  255.                 printf ("\n     Located %d bytes into file.",*file_byte_cnt);
  256.                 exit (2);
  257.             }
  258.         }
  259.     }
  260.  
  261.     (*file_byte_cnt)++;
  262.                     
  263.     possbytes = (unsigned long) width * height;
  264.     i = 8 / bits_to_use;
  265.     possbytes = possbytes / i;
  266.     printf ("\nTotal number of bytes in image:  %ld out of possible  %ld\n",
  267.                                                        bytetot, possbytes);
  268.  
  269.     if (data_byte_cnt == EOF)
  270.     {
  271.         (*file_byte_cnt)--;
  272.         printf ("\n? -- EOF reached before zero byte count");
  273.         printf ("\n     of image was read.\n");
  274.         printf ("\n     Located %d bytes into file.",*file_byte_cnt);
  275.         exit (3);
  276.     }
  277. }
  278.  
  279. /************************************************************************/
  280.  
  281. /* EXTNINFO - routine to read the GIF file for extension data and       */
  282. /*            display it to the screen in an orderly fasion.  This      */
  283. /*            extension information may be located before, between, or  */
  284. /*            after any of the image data.                              */
  285.  
  286. extninfo(dev, file_byte_cnt)
  287. FILE *dev;
  288. int *file_byte_cnt;
  289.  
  290. {
  291.     int byte1;
  292.     int byte2;
  293.     int i;
  294.     int data_byte_cnt;
  295.  
  296.     unsigned long bytetot;
  297.  
  298.             /* retrieve the function code */
  299.  
  300.     byte1 = getc(dev);
  301.     (*file_byte_cnt)++;
  302.     printf ("\nGIF extension code %d located at byte %d", byte1,
  303.                                                           *file_byte_cnt);
  304.  
  305.             /* tally up the total bytes and read past each data block */
  306.  
  307.     bytetot = 0;
  308.  
  309.     while ((data_byte_cnt = getc(dev)) > 0)
  310.     {                
  311.         (*file_byte_cnt)++;
  312.         bytetot = bytetot + data_byte_cnt;
  313.         for (i = 0; (i < data_byte_cnt); i++)
  314.         {
  315.             byte2 = getc(dev);
  316.             (*file_byte_cnt)++;
  317.             if (byte2 == EOF)
  318.             {
  319.                 (*file_byte_cnt)--;
  320.                 printf ("\n? -- EOF was reached inside extension data block.\n");
  321.                 printf ("\n     Located %d bytes into file.",*file_byte_cnt);
  322.                 exit (2);
  323.             }
  324.         }
  325.     }
  326.  
  327.     (*file_byte_cnt)++;
  328.     printf ("\nTotal number of bytes in extension:  %ld\n", bytetot);
  329.  
  330.     if (data_byte_cnt == EOF)
  331.     {
  332.         (*file_byte_cnt)--;
  333.         printf ("\n? -- EOF was reached before zero byte count");
  334.         printf ("\n     of extension was read.\n");
  335.         printf ("\n     Located %d bytes into file.",*file_byte_cnt);
  336.         exit (3);
  337.     }
  338. }
  339.  
  340. /************************************************************************/
  341.  
  342. /* CHKUNEXP - routine to check for any unexpected nonzero data found    */
  343. /*            within the GIF file.  This routine will help determine    */
  344. /*            where the unexpected data may reside in the file.         */
  345.  
  346. chkunexp (unexpected, determiner)
  347. int *unexpected;
  348. int determiner;
  349.  
  350. {
  351.  
  352.             /* Determine place in the GIF file */
  353.  
  354.     if (determiner > 0)
  355.     {
  356.         printf ("\n? -- %d bytes of unexpected data found before",
  357.                                                       *unexpected);
  358.         printf ("\n     image %d.\n", determiner);
  359.     }
  360.     else if (determiner == -1)
  361.     {
  362.         printf ("\n? -- %d bytes of unexpected data found before",
  363.                                                       *unexpected);
  364.         printf ("\n     GIF file terminator.\n");
  365.     }
  366.     else if (determiner == -2)
  367.     {
  368.         printf ("\n? -- %d bytes of unexpected data found after",
  369.                                                       *unexpected);
  370.         printf ("\n     GIF file terminator.\n");
  371.     }
  372.     else
  373.     {
  374.         printf ("\n? -- %d bytes of unexpected data found at",
  375.                                                       *unexpected);
  376.         printf ("\n     or after expected GIF terminator byte.\n");
  377.     }
  378.  
  379.             /* Zero out the unexpected variable for */
  380.             /* the next group that may be encountered */
  381.  
  382.     *unexpected = 0;
  383. }
  384.  
  385. /************************************************************************/
  386.  
  387. /* MAIN - the main routine reads the GIF file for the global GIF        */
  388. /*        information which it displays to the user's screen.  This     */
  389. /*        routine also determines which subroutine to call and which    */
  390. /*        information to process.                                       */
  391.  
  392.  
  393. main(argc, argv)
  394. char *argv[];
  395. int argc;
  396.  
  397. #define DECIMAL 1
  398. #define PERCENT 2
  399. #define HEXIDEC 3
  400.  
  401. {
  402.     char filename[15];
  403.     char version[7];
  404.     char style[5];
  405.  
  406.     int byte1;
  407.     int byte2;
  408.     int byte3;
  409.     int image_left;
  410.     int image_top;
  411.     int data_byte_cnt;
  412.     int image_cnt;
  413.     int bits_per_pix;
  414.     int bits_to_use;
  415.     int color_res;
  416.     int colors;
  417.     int i;
  418.     int globl;
  419.     int end_gif_fnd;
  420.     int unexpected;
  421.     int color_style;
  422.     int switch_present;
  423.     int file_byte_cnt;
  424.  
  425.     unsigned int width;
  426.     unsigned int height;
  427.  
  428.     FILE *in;
  429.  
  430.             /* Start of Processing */
  431.  
  432.             /* If just one argument then display the message */
  433.  
  434.     if (argc == 1)
  435.     {
  436.         printf ("\nUSAGE:    gifscan  color_opt  filename\n");
  437.         printf ("\ncolor_opt   specifies how color lookup table");
  438.         printf ("\n            definitions are displayed");
  439.         printf ("\n  -h  :     output as hexidecimal (0 - FF) (default)");
  440.         printf ("\n  -d  :     output as decimal (0 - 255)");
  441.         printf ("\n  -p  :     output as percentage (0 - 100)\n");
  442.         exit (0);
  443.     }
  444.  
  445.     color_style = 0;
  446.     switch_present = 0;
  447.  
  448.     while ((i = getopt(argc, argv, "dhpqD")) != EOF) {
  449.         switch (i) {
  450.         case 'd': /* decimal */
  451.             color_style = DECIMAL;
  452.             break;
  453.         case 'p': /* percent */
  454.             color_style = PERCENT;
  455.             break;
  456.         case 'h': /* hexadecimal */
  457.             color_style = HEXIDEC;
  458.             break;
  459.         case 'q': /* set quiet flag */
  460.             Quiet = 1;
  461.             break;
  462.         case 'D': /* debug (undoc) */
  463.             Debug = 1;
  464.             break;
  465.         default:
  466.             exit(1);
  467.         }
  468.     }
  469.  
  470.             /* Check for GIF filename */
  471.  
  472.     if (argc == optind) {
  473.         fprintf(stderr, "Missing filename(s)\nType gifscn for help\n");
  474.         exit(1);
  475.     }
  476.     else {
  477.         if (Debug) fprintf(stderr, "Filename: %s\n", argv[optind]);
  478.         /* copy the filename and open it */
  479.         strcpy(filename, argv[optind]);
  480.         in = fopen(filename, "rb");
  481.         if (in == NULL) {
  482.             fprintf(stderr, "Can't open file %s\n", filename);
  483.             exit(1);
  484.         }
  485.     }
  486.  
  487.     image_cnt = 0;
  488.     end_gif_fnd = 0;
  489.     unexpected = 0;
  490.     file_byte_cnt = 0;
  491.  
  492.             /* get version from file */
  493.  
  494.     if ((version[0] = getc(in)) == 0x47)
  495.     {
  496.         for (i = 1; (i < 6); i++)
  497.             version[i] = getc(in);
  498.         version[6] = '\0';
  499.         printf ("\nVersion: %s", version);
  500.     }
  501.     else
  502.     {
  503.         printf ("\n? -- NOT a GIF file\n");
  504.         exit(1);
  505.     }
  506.  
  507.     file_byte_cnt += 6;
  508.  
  509.             /* determine screen width */
  510.  
  511.     width = getbytes(in, &file_byte_cnt);
  512.  
  513.             /* determine screen height */
  514.  
  515.     height = getbytes(in, &file_byte_cnt);
  516.     printf ("\nScreen Width:      %5d\tScreen Height:     %5d", width,
  517.                                                                 height);
  518.  
  519.             /* check for a Global Map */
  520.  
  521.     byte1 = getc(in);
  522.     file_byte_cnt++;
  523.  
  524.     byte2 = byte1 & 0x80;
  525.     if (byte2 == 0x80)
  526.     {
  527.         printf ("\nGlobal Color Map: Yes");
  528.         globl = 1;
  529.     }
  530.     else
  531.     {
  532.         printf ("\nGlobal Color Map: No");
  533.         globl = 0;
  534.     }
  535.  
  536.             /* Check for the 0 bit */
  537.  
  538.     byte2 = byte1 & 0x08;
  539.     if (byte2 != 0)
  540.         printf ("\n? -- Reserved zero bit is not zero.\n");
  541.  
  542.             /* determine the color resolution */
  543.  
  544.     byte2 = byte1 & 0x70;
  545.     color_res = byte2 >> 4;
  546.  
  547.             /* get the background index */
  548.  
  549.     byte3 = getc(in);
  550.     file_byte_cnt++;
  551.     printf ("\nColor resolution:  %5d\tBackground index:  %5d",
  552.                                                      ++color_res,
  553.                                                           byte3);
  554.  
  555.             /* determine the bits per pixel */
  556.  
  557.     bits_per_pix = byte1 & 0x07;
  558.     bits_per_pix++;
  559.     bits_to_use = bits_per_pix;
  560.  
  561.             /* determine # of colors in global map */
  562.  
  563.     colors = 1 << bits_per_pix;
  564.     printf ("\nBits per pixel:    %5d\t# colors:          %5d\n", bits_per_pix,
  565.                                                                 colors);
  566.  
  567.             /* check for the 0 byte */
  568.  
  569.     byte1 = getc(in);
  570.     file_byte_cnt++;
  571.     if (byte1 != 0)
  572.         printf ("\n? -- Reserved byte after Background index is not zero.\n");
  573.  
  574.     if (globl == 1)
  575.         colormap (color_style, in, colors, &file_byte_cnt);
  576.  
  577.             /* check for the zero byte count, a new image, or */
  578.             /* the end marker for the gif file */
  579.  
  580.     while ((byte1 = getc(in)) != EOF)
  581.     {
  582.         file_byte_cnt++;
  583.         if (byte1 == ',')
  584.         {
  585.             image_cnt++;
  586.             if (unexpected != 0)
  587.                 chkunexp (&unexpected, image_cnt);
  588.             printf ("\nImage # %2d separator located at byte %d.",
  589.                                              image_cnt, file_byte_cnt);
  590.  
  591.             imageinf (in, bits_to_use, color_style, &file_byte_cnt);
  592.         }
  593.  
  594.         else if (byte1 == '!')
  595.  
  596.             /* Extension data found */
  597.  
  598.             extninfo (in, &file_byte_cnt);
  599.  
  600.         else if (byte1 == ';')
  601.  
  602.             /* GIF terminator located, check for any */
  603.             /* unexpected data found before terminator */
  604.  
  605.         {
  606.             if (unexpected != 0)
  607.                 chkunexp (&unexpected, -1);
  608.             end_gif_fnd = 1;
  609.             printf ("\nGIF terminator located at byte %d.\n",
  610.                                                  file_byte_cnt);
  611.         }
  612.  
  613.         else
  614.             unexpected++;
  615.     }
  616.  
  617.             /* EOF has been reached - check last bytes read */
  618.  
  619.     if (end_gif_fnd == 0)
  620.     {
  621.         printf ("\n? -- GIF file terminator ';' was not found.");
  622.         printf ("\n     Expected at byte %d in file.\n",file_byte_cnt);
  623.     }
  624.     if ((unexpected != 0) && (end_gif_fnd == 0))
  625.         chkunexp (&unexpected, -3);
  626.     else if (unexpected != 0)
  627.         chkunexp (&unexpected, -2);
  628. }
  629.